package com.inspur.edp.bef.bizentity.common;

import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityErrorCodeEnum;
import com.inspur.edp.bef.bizentity.exceptions.BusinessEntityException;
import com.inspur.edp.cef.designtime.api.json.CefNames;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

import com.inspur.edp.bef.bizentity.collection.DtmElementCollection;
import com.inspur.edp.bef.bizentity.operation.*;
import com.inspur.edp.bef.bizentity.operation.collection.DeterminationCollection;
import com.inspur.edp.bef.bizentity.operation.collection.ValidationCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonValCollection;
import com.inspur.edp.cef.designtime.api.collection.ValElementCollection;
import com.inspur.edp.cef.designtime.api.operation.*;
import com.inspur.edp.bef.bizentity.beenum.BETriggerTimePointType;
import com.inspur.edp.bef.bizentity.beenum.RequestNodeTriggerType;
import java.util.Map.Entry;

//using Inspur.Gsp.Bef.BizEntity.Enum;

/**
 * bizOp=>commonOp转换
 */
public class OperationConvertUtils {
	/**
	 * 转换联动计算列表
	 *
	 * @param dtms 联动计算集合
	 * @param type 触发时机
	 * @return
	 */
	public static CommonDtmCollection convertToCommonDtms(DeterminationCollection dtms, BETriggerTimePointType type) {
		CommonDtmCollection cDtms = new CommonDtmCollection();
		for (BizOperation op : dtms) {
			Determination dtm = (Determination) op;
			if (dtm.getTriggerTimePointType().contains(type)) {
				cDtms.add(convertToCommonDtm(dtm));
			}
		}
		return cDtms;
	}

	public static DeterminationCollection convertToDtmCollection(CommonDtmCollection dtms, BETriggerTimePointType type) {
		DeterminationCollection dtmCollection = new DeterminationCollection();
		for (CommonDetermination op : dtms) {
			BizCommonDetermination commonDetermination = (BizCommonDetermination) op;
			dtmCollection.add(convertToDetermination(commonDetermination, type));
		}
		return dtmCollection;
	}

	/**
	 * 转换校验规则列表
	 *
	 * @param vals
	 * @return
	 */
	public static CommonValCollection convertToCommonValidations(ValidationCollection vals, BETriggerTimePointType type) {
		CommonValCollection cVals = new CommonValCollection();
		for (BizOperation op : vals) {
			Validation val = (Validation) op;
			if (val.getValidationTriggerPoints().containsKey(type) && val.getValidationTriggerPoints().get(type).size() > 0) {
				cVals.add(convertToCommonValidation(val, type));
			}
		}
		return cVals;
	}

	// region 私有方法
	public static CommonDetermination convertToCommonDtm(Determination dtm) {
		BizCommonDetermination cDtm = new BizCommonDetermination();
		convertToCommonOperation(cDtm, dtm);
		cDtm.setParameterCollection(dtm.getParameterCollection());
		cDtm.setRunOnce(dtm.getRunOnce());
		cDtm.setGetExecutingDataStatus(getExecutingDataStatus(dtm.getRequestNodeTriggerType()));
		if (dtm.getRequestElements().size() > 0) {
			for (String item : dtm.getRequestElements()) {
				cDtm.getRequestElements().add(item);
			}
		}
		if(dtm.getRequestChildElements() != null && dtm.getRequestChildElements().size() > 0){
//			HashMap<String, ChildDtmTriggerInfo> hashMap = new HashMap<String, ChildDtmTriggerInfo>();
			HashMap<String, com.inspur.edp.cef.designtime.api.collection.DtmElementCollection> childEls = new HashMap<>();
			for(Map.Entry<String, DtmElementCollection> item : dtm.getRequestChildElements().entrySet()){
				com.inspur.edp.cef.designtime.api.collection.DtmElementCollection collection =
						new com.inspur.edp.cef.designtime.api.collection.DtmElementCollection();
				if(item.getValue() != null) {
					for (String s : item.getValue()) {
						collection.add(s);
					}
				}
				childEls.put(item.getKey(), collection);
			}
			cDtm.setRequestChildElements(childEls);
//			cDtm.setChildTriggerInfo(hashMap);
		}
		return cDtm;
	}

	public static Determination convertToDtm(CommonDetermination common,
			String triggerTimePointType, GspBizEntityObject parent)  {
		Determination operation = new Determination();
		operation.setID(common.getID());
		operation.setCode(common.getCode());
		operation.setName(common.getName());
		operation.setDescription(common.getDescription());
		operation.setComponentId(common.getComponentId());
		operation.setComponentName(common.getComponentName());
		operation.setComponentPkgName(common.getComponentPkgName());
		operation.setOwner(parent);
		operation.setTriggerTimePointType(EnumSet.of(convert2TriggerTimePointType(
				triggerTimePointType, common.getTriggerPointType())));
		operation.setIsGenerateComponent(common.getIsGenerateComponent());
		return operation;
	}

	public static Validation convertToVal(CommonValidation common,
			String triggerTimePointType, GspBizEntityObject parent)  {
		Validation operation = new Validation();
		operation.setID(common.getID());
		operation.setCode(common.getCode());
		operation.setName(common.getName());
		operation.setDescription(common.getDescription());
		operation.setComponentId(common.getComponentId());
		operation.setComponentName(common.getComponentName());
		operation.setComponentPkgName(common.getComponentPkgName());
		operation.setOwner(parent);
		operation.getValidationTriggerPoints().put(
				convert2TriggerTimePointType(triggerTimePointType,
						common.getTriggerPointType()), EnumSet.of(RequestNodeTriggerType.Created));
		operation.setIsGenerateComponent(common.getIsGenerateComponent());
		return operation;
	}

	public static Determination convertToDetermination(BizCommonDetermination commonDetermination, BETriggerTimePointType type) {
		Determination dtm = new Determination();
		dtm.setID(commonDetermination.getID());
		dtm.setCode(commonDetermination.getCode());
		dtm.setName(commonDetermination.getName());
		dtm.setDescription(commonDetermination.getDescription());
		dtm.setComponentId(commonDetermination.getComponentId());
		dtm.setComponentName(commonDetermination.getComponentName());
		dtm.setComponentPkgName(commonDetermination.getComponentPkgName());
		dtm.setParameterCollection(commonDetermination.getParameterCollection());
		dtm.setRunOnce(dtm.getRunOnce());
		if (commonDetermination.getRequestElements().size() > 0) {
			for (String item : dtm.getRequestElements()) {
				dtm.getRequestElements().add(item);
			}
		}
		dtm.setRequestNodeTriggerType(getRequestNodeTriggerType(commonDetermination.getGetExecutingDataStatus()));
		EnumSet<BETriggerTimePointType> enumSet = EnumSet.noneOf(BETriggerTimePointType.class);
		enumSet.add(type);
		dtm.setTriggerTimePointType(enumSet);
		return dtm;
	}

	public static CommonValidation convertToCommonValidation(Validation validation, BETriggerTimePointType type) {
		BizCommonValdation cValidation = new BizCommonValdation();
		convertToCommonOperation(cValidation, validation);
		cValidation.setParameterCollection(validation.getParameterCollection());
		if (validation.getRequestElements().size() > 0) {
			for (String item : validation.getRequestElements()) {
				cValidation.getRequestElements().add(item);
			}
		}
		EnumSet<RequestNodeTriggerType> triggerTypes = validation.getValidationTriggerPoints().get(type);
		cValidation.setGetExecutingDataStatus(getExecutingDataStatus(triggerTypes));

		if(validation.getRequestChildElements() != null && validation.getRequestChildElements().size() > 0){
			for(Entry<String, ValElementCollection> item : validation.getRequestChildElements().entrySet()){
				com.inspur.edp.cef.designtime.api.collection.ValElementCollection collection =
						new com.inspur.edp.cef.designtime.api.collection.ValElementCollection();
				if(item.getValue() != null) {
					for (String s : item.getValue()) {
						collection.add(s);
					}
				}
				cValidation.getRequestChildElements().put(item.getKey(), collection);
			}
		}
		return cValidation;
	}

	/**
	 * 触发时机转换
	 *
	 * @param enumSet
	 * @return
	 */
	private static EnumSet<ExecutingDataStatus> getExecutingDataStatus(EnumSet<RequestNodeTriggerType> enumSet) {
		EnumSet<ExecutingDataStatus> set = EnumSet.noneOf(ExecutingDataStatus.class);
		boolean isadded = enumSet.contains(RequestNodeTriggerType.Created);
		if (isadded) {
			set.add(ExecutingDataStatus.added);
		}
		boolean isModify = enumSet.contains(RequestNodeTriggerType.Updated);
		if (isModify) {
			set.add(ExecutingDataStatus.Modify);
		}
		boolean isDeleted = enumSet.contains(RequestNodeTriggerType.Deleted);
		if (isDeleted) {
			set.add(ExecutingDataStatus.Deleted);
		}
		return set;
	}

	//老联动默认加上所有时机
	private static EnumSet<ExecutingDataStatus> getAllChildExecutingDataStatus() {
		EnumSet<ExecutingDataStatus> set = EnumSet.noneOf(ExecutingDataStatus.class);
		set.add(ExecutingDataStatus.added);
		set.add(ExecutingDataStatus.Modify);
		set.add(ExecutingDataStatus.Deleted);
		return set;
	}

	private static EnumSet<RequestNodeTriggerType> getRequestNodeTriggerType(EnumSet<ExecutingDataStatus> enumSet) {
		EnumSet<RequestNodeTriggerType> set = EnumSet.noneOf(RequestNodeTriggerType.class);
		boolean isadded = enumSet.contains(ExecutingDataStatus.added);
		if (isadded) {
			set.add(RequestNodeTriggerType.Created);
		}
		boolean isModify = enumSet.contains(ExecutingDataStatus.Modify);
		if (isModify) {
			set.add(RequestNodeTriggerType.Updated);
		}
		boolean isDeleted = enumSet.contains(ExecutingDataStatus.Deleted);
		if (isDeleted) {
			set.add(RequestNodeTriggerType.Deleted);
		}
		return set;
	}

	/**
	 * commonOperation基类属性转换
	 *
	 * @param commonOp
	 * @param bizOp
	 */
	private static void convertToCommonOperation(CommonOperation commonOp, BizOperation bizOp) {
		commonOp.setID(bizOp.getID());
		commonOp.setCode(bizOp.getCode());
		commonOp.setName(bizOp.getName());
		commonOp.setDescription(bizOp.getDescription());
		commonOp.setComponentId(bizOp.getComponentId());
		commonOp.setComponentName(bizOp.getComponentName());
		commonOp.setComponentPkgName(bizOp.getComponentPkgName());
	}

	private static BETriggerTimePointType convert2TriggerTimePointType(String value,
			CommonTriggerPointType trigger) {
		if(value == null){
			return BETriggerTimePointType.None;
		}
		switch(value) {
			case CefNames.DtmAfterCreate:
				return BETriggerTimePointType.RetrieveDefault;
			case CefNames.DtmAfterModify:
			case BizEntityJsonConst.ValueChangedDtm:
			case BizEntityJsonConst.ValueChangedVal:
			case BizEntityJsonConst.ComputationDtm:
			case CefNames.ValAfterModify:
				return BETriggerTimePointType.AfterModify;
			case CefNames.DtmBeforeSave:
			case CefNames.ValBeforeSave:
				return BETriggerTimePointType.BeforeCheck;
			case BizEntityJsonConst.B4QueryDtm:
				return BETriggerTimePointType.BeforeQuery;
			case BizEntityJsonConst.AftQueryDtm:
				return BETriggerTimePointType.AfterQuery;
			case BizEntityJsonConst.DtmCancel:
				return BETriggerTimePointType.Cancel;
			case BizEntityJsonConst.B4RetrieveDtm:
				return BETriggerTimePointType.BeforeRetrieve;
			case BizEntityJsonConst.AftLoadingDtm:
				return BETriggerTimePointType.AfterLoading;
			case BizEntityJsonConst.ItemDeletingDtm:
			case BizEntityJsonConst.ItemDeletingVal:{
				switch(trigger){
					case AfterModify:
						return BETriggerTimePointType.AfterModify;
					case BeforeSave:
						return BETriggerTimePointType.BeforeCheck;
					default:
						return BETriggerTimePointType.None;
				}
			}
			case BizEntityJsonConst.ValidationAfterSave:
				return BETriggerTimePointType.AfterSave;
			default:
				throw BusinessEntityException.createException(BusinessEntityErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0010, value);
		}
	}
	// endregion
}